package com.rulestech.engine.drools;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatelessKnowledgeSession;

import com.rulestech.engine.AbstractDecisionEngine;
import com.rulestech.engine.EngineContext;
import com.rulestech.engine.EngineLogger;
import com.rulestech.engine.EngineResult;

public abstract class DecisionEngineInDrools extends AbstractDecisionEngine {
	private static Logger theLogger = Logger.getLogger(DecisionEngineInDrools.class.getName());

	public abstract String[] getRuleBases();
	public abstract String getRuleFlow();
	
	
	@Override
	public void invoke(EngineContext context, EngineResult result, EngineLogger log) throws Exception {
		KnowledgeBase kbase = getKnowledgeBaseFromDRL();
		StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
		KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
		List <Object> objects = new ArrayList <Object>();
		objects.add(context);
		objects.add(result);
		objects.add(log);
		ksession.execute(objects);
		logger.close();
	}

	
	/**
	 * Get the knowledge base from the DRL files
	 * @return
	 * @throws Exception
	 */
	private KnowledgeBase getKnowledgeBaseFromDRL() throws Exception {
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
		String[] ruleBaseNames = getRuleBases();
		for (String ruleBaseName: ruleBaseNames){
			kbuilder.add(ResourceFactory.newClassPathResource(ruleBaseName), ResourceType.DRL);	
		}
		KnowledgeBuilderErrors errors = kbuilder.getErrors();
		if (errors.size() > 0) {
			for (KnowledgeBuilderError error: errors) {
				theLogger.severe(error.getMessage());
			}
			throw new IllegalArgumentException("Could not parse knowledge.");
		}
		KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
		kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
		return kbase;
	}
	
	
	/**
	 * Get the knowledge base from the rule flow file.
	 * @return
	 * @throws Exception
	 */
	private KnowledgeBase getKnowledgeBaseFromRuleFlow() throws Exception {
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
		kbuilder.add(ResourceFactory.newClassPathResource(getRuleFlow()), ResourceType.DRF);
		KnowledgeBuilderErrors errors = kbuilder.getErrors();
		if (errors.size() > 0) {
			for (KnowledgeBuilderError error: errors) {
				theLogger.severe(error.getMessage());
			}
			throw new IllegalArgumentException("Could not parse knowledge.");
		}
		KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
		kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
		return kbase;
	}
}
 
